package com.qiaomeng.flutter.android_device;

import android.content.Context;
import android.os.Build;
import android.provider.Settings;

import androidx.annotation.NonNull;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/** AndroidDevicePlugin */
public class AndroidDevicePlugin implements FlutterPlugin, MethodCallHandler {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private MethodChannel channel;
  private Context context;

  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
    channel = new MethodChannel(flutterPluginBinding.getFlutterEngine().getDartExecutor(), "android_device");
    channel.setMethodCallHandler(this);
    context = flutterPluginBinding.getApplicationContext();
  }

  // This static function is optional and equivalent to onAttachedToEngine. It supports the old
  // pre-Flutter-1.12 Android projects. You are encouraged to continue supporting
  // plugin registration via this function while apps migrate to use the new Android APIs
  // post-flutter-1.12 via https://flutter.dev/go/android-project-migration.
  //
  // It is encouraged to share logic between onAttachedToEngine and registerWith to keep
  // them functionally equivalent. Only one of onAttachedToEngine or registerWith will be called
  // depending on the user's project. onAttachedToEngine or registerWith must both be defined
  // in the same class.
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "android_device");
    channel.setMethodCallHandler(new AndroidDevicePlugin());
  }

  @Override
  public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
    if (call.method.equals("getDeviceId")) {
      result.success(getDeviceId());
    } else {
      result.notImplemented();
    }
  }

  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    channel.setMethodCallHandler(null);
  }

  public String md5(String input) {
    try {
      byte[] bytes = MessageDigest.getInstance("MD5").digest(input.getBytes());
      return printHexBinary(bytes);
    } catch (NoSuchAlgorithmException e) {
      return input;
    }
  }

  public String printHexBinary(byte[] data) {
    StringBuilder r = new StringBuilder(data.length * 2);
    for (byte b : data) {
      r.append(String.format("%02X", new Integer(b & 0xFF)));
    }
    return r.toString();
  }

  public String getDeviceId() {
    String ANDROID_ID = Settings.Secure.getString(
            context.getContentResolver(),
            Settings.Secure.ANDROID_ID
    );
    String SERIAL = Build.SERIAL;
    String FINGERPRINT = Build.FINGERPRINT;
    long TIME = Build.TIME;
    String INCREMENTAL = Build.VERSION.INCREMENTAL;
    String RadioVersion = Build.getRadioVersion();
    String HARDWARE = Build.HARDWARE;
    String BOARD = Build.BOARD;
    String DEVICE = Build.DEVICE;
    String MANUFACTURER = Build.MANUFACTURER;

    String s = ANDROID_ID + SERIAL + FINGERPRINT + TIME + INCREMENTAL + RadioVersion + HARDWARE + BOARD + DEVICE + MANUFACTURER;
    return md5(s);
  }
}
